package com.zbq.scbasegateway.routes.filter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.MetricsEndpoint;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * 根据CPU的使用情况限流
 */
@Slf4j
@Order( -999)
@Component
public class LimitByCPUGatewayFilterFactory extends AbstractGatewayFilterFactory<LimitByCPUGatewayFilterFactory.Config> {

    @Autowired
    private MetricsEndpoint metricsEndpoint;

    private static final String METRIC_NAME = "system.cpu.usage";


    public LimitByCPUGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            //获取网关所在机器的CPU使用情况
            Double systemCpuUsage = metricsEndpoint.metric(METRIC_NAME, null)
                    .getMeasurements()
                    .stream()
                    .filter(Objects::nonNull)
                    .findFirst()
                    .map(MetricsEndpoint.Sample::getValue)
                    .filter(Double::isFinite)
                    .orElse(0.0D);

            boolean isOpenRateLimit = systemCpuUsage >config.getMAX_USAGE();
            log.debug("system.cpu.usage: {}, isOpenRateLimit:{} ",systemCpuUsage , isOpenRateLimit);
            if (isOpenRateLimit) {
                //当CPU的使用超过设置的最大阀值开启限流
                exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                return exchange.getResponse().setComplete();
            } else {
                return chain.filter(exchange);
            }
        };
    }

    @Data
    public static class Config {
        private double MAX_USAGE = 0.50D;
    }

}